---
title: 导入参考
description: 学习如何导入不同的文件类型到你的 Astro 项目中。
i18nReady: true
---
import RecipeLinks from "~/components/RecipeLinks.astro";
import ReadMore from '~/components/ReadMore.astro'

Astro 无需配置即支持大多数静态资源。你可以在项目的任何地方使用 `import` 语句（包括 Astro frontmatter 脚本），Astro 将在最终构建中内置优化后的静态资源副本。在 CSS 和 `<style>` 标签中也可以使用 `@import`。

## 受支持的文件类型

下面的文件类型 Astro 开箱即用：

- Astro 组件 (`.astro`)
- Markdown (`.md`，`.markdown`，等等)
- JavaScript (`.js`，`.mjs`)
- TypeScript (`.ts`)
- NPM 包
- JSON (`.json`)
- CSS (`.css`)
- CSS 模块 (`.module.css`)
- 图片和资源 (`.svg`，`.jpg`，`.png`，等等。)

此外，你可以扩展 Astro 以添加对不同 [UI 框架](/zh-cn/guides/framework-components/)的支持，如 React、Svelte 和 Vue 组件。你还可以安装 [Astro MDX 集成](/zh-cn/guides/integrations-guide/mdx/) 或 [Astro Markdoc 集成](/zh-cn/guides/integrations-guide/markdoc/) 在项目中使用 `.mdx` 或者 `.mdoc` 文件。

### `public/` 中的文件

你可以将任何静态资源放在项目的 [`public/` 目录](/zh-cn/basics/project-structure/#public)中，Astro 将直接将其复制到最终构建中，而不会对其进行任何处理。`public/` 文件不会被 Astro 构建或打包，这意味着支持任何类型的文件。

你可以直接在模板中通过 URL 路径引用 `public/` 文件。

```astro
// 链接到 /public/reports/annual/2024.pdf
Download the <a href="/reports/annual/2024.pdf">2024 annual statement as a PDF</a>.

// 显示 /public/assets/cats/ginger.jpg
<img src="/assets/cats/ginger.jpg" alt="An orange cat sleeping on a bed.">
```

## Import 语句

Astro 使用 ESM，它是浏览器中支持的相同 [`import`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/import#syntax) 和 [`export`](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Statements/export) 语法。

### JavaScript

```js
import { getUser } from './user.js';
```

可以使用普通的 ESM `import` 和 `export` 语法来导入 JavaScript。它在 Node.js 和浏览器中和预期保持一致。

:::note[导入 JSX 文件]

渲染 JSX/TSX 文件需要适当的 [UI 框架](/zh-cn/guides/framework-components/)（[React](/zh-cn/guides/integrations-guide/react/)、[Preact](/zh-cn/guides/integrations-guide/preact/) 或 [Solid](/zh-cn/guides/integrations-guide/solid-js/)）。
在适当的情况下使用 `.jsx`/`.tsx` 扩展名，因为 Astro 不支持 `.js`/`.ts` 文件中的 JSX。

:::

### TypeScript

```js
import { getUser } from './user';
import type { UserType } from './user';
```

Astro 内置对 [TypeScript](https://www.typescriptlang.org/) 的支持。你可以在 Astro 项目中直接导入 `.ts` 和 `.tsx` 文件，甚至可以直接在 [Astro 组件脚本](/zh-cn/basics/astro-components/#组件脚本)和任意 [script 标签](/zh-cn/guides/client-side-scripts/) 中编写 TypeScript 代码。

**Astro 本身不进行任何类型检查**。类型检查应该在 Astro 之外进行或由 IDE 或通过一个单独的脚本来处理。[Astro VSCode 扩展](/zh-cn/editor-setup/) 会自动为打开的文件中提供 TypeScript 提示和错误警告。或使用 [`astro check` 命令](/zh-cn/reference/cli-reference/#astro-check) 检查 Astro 文件的类型。

:::note[TypeScript 和文件扩展名]
根据 [TypeScript 模块解决方案规则](https://www.typescriptlang.org/docs/handbook/module-resolution.html)，`.ts` 和 `.tsx` 文件扩展名不应该在导入 TypeScript 文件时使用。相反，要么使用`.js`/`.jsx`文件扩展名，要么完全省略文件扩展名。

```ts
import { getUser } from './user.js'; // user.ts
import MyComponent from "./MyComponent"; // MyComponent.tsx
```

:::

<ReadMore>了解更多关于 [Astro 中的 TypeScript 支持](/zh-cn/guides/typescript/) 的内容。</ReadMore>

### NPM 包

如果你安装了一个 NPM 包，你可以在 Astro 中导入它。

```astro
---
import { Icon } from 'astro-icon';
---
```
如果一个包使用了旧的格式发布，Astro 将尝试将包转换为 ESM，以便 `import` 语句可以正常工作。在某些情况下，你可能需要调整你的 [`vite` 配置](/zh-cn/reference/configuration-reference/#vite) 以使其正常工作。

:::caution
一些包依赖于浏览器环境。Astro 组件在服务器上运行，因此在 frontmatter 导入这些包可能会[导致错误](/zh-cn/guides/troubleshooting/#document-or-window-is-not-defineddocument-或-window-对象未定义)。
:::

### JSON

```js
// 使用默认导入加载 JSON 对象
import json from './data.json';
```

Astro 支持直接在应用程序中导入 JSON 文件。导入文件会通过默认导入返回完整的 JSON 对象。

### CSS

```js
// 加载并将 'style.css' 注入到页面上。
import './style.css';
```

Astro 支持直接在应用程序中导入 CSS 文件。导入的样式没有暴露出口，但导入样式会自动将这些样式添加到页面中。它默认支持所有 CSS 文件，并且可以通过插件支持 CSS 编译语言，如 Sass & Less。

<ReadMore>在 [样式指南](/zh-cn/guides/styling/#高级) 中阅读有关高级 CSS 导入用例的更多信息，例如直接通过 URL 引用 CSS 文件，或将 CSS 作为字符串导入。</ReadMore>

### CSS 模块

```jsx
// 1. 将 './style.module.css' 转换为类名唯一、有范围的值。
// 2. 返回对象，并将原始类名映射到其最终范围值的。
import styles from './style.module.css';

// This example uses JSX, but you can use CSS Modules with any framework.
return <div className={styles.error}>Your Error Message</div>;
```

Astro 支持使用 `[name].module.css` 命名约定的 CSS 模块。像导入任何 CSS 文件一样，导入 CSS 会应用到页面。然而，CSS 模块默认导出特殊的 `styles` 对象，并将你的原始类名映射到唯一的标识符。

CSS 模块帮助你在前端强制执行组件样式隔离，并生成唯一的样式表类名。

### 其他资源

```jsx
// 返回带有 `src` 和其他属性的对象
import imgReference from './image.png';
import svgReference from './image.svg';

// HTML 或者 UI 框架组件可以用它们来渲染图片
<img src={imgReference.src} alt="image description" />;

// Astro 的 `<Image />` 和 `<Picture />` 组件会默认访问 `src`
<Image src={imgReference} alt="image description">
```

所有其他没有明确提到的资源可以通过 ESM 的 `import` 语句导入，并将返回最终构建中的资源的 URL 引用（例如 `/_astro/my-video.C7vXpQtF.mp4`）而不是一个对象。

这对使用 URL 引用非 JS 资源很有用，比如创建一个带有 `src` 属性的图片元素指向该图片。

将图片和其他资源放在 `public/` 文件夹中也很有用，这在[项目结构页面](/zh-cn/basics/project-structure/#public)中有所解释。

<ReadMore>有关附加 Vite 导入参数（例如 `?url`、`?raw`）的更多信息，请参阅 [Vite 静态资源处理指南](https://cn.vite.dev/guide/assets)。</ReadMore>

:::note
鼓励将**替代文本**添加到 `<img>` 标记以提高可访问性！不要忘记向图像元素添加 `alt="一段有用的描述"` 属性。如果图像纯粹是装饰性的，则可以将该属性留空。
:::

## 别名

**别名**可以用于创建简洁的导入。

别名有助于改善在项目中大量使用绝对或相对引用的体验。

```astro title="src/pages/about/company.astro" del="../../components" del="../../assets"
---
import Button from '../../components/controls/Button.astro';
import logoUrl from '../../assets/logo.png?url';
---
```

在这个示例中，开发者需要理解 `src/pages/about/company.astro`, `src/components/controls/Button.astro` 和 `src/assets/logo.png` 间的关系。如果移动了 `company.astro` 文件，那么这些导入也都需要更新。

你可以在 `tsconfig.json` 中添加导入别名。

```json title="tsconfig.json" ins={4-5}
{
  "compilerOptions": {
    "paths": {
      "@components/*": ["./src/components/*"],
      "@assets/*": ["./src/assets/*"]
    }
  }
}
```

在这个配置更改完之后，开发服务器会自动重启。然后，你可以在项目中的任何地方使用这些别名进行导入：

```astro title="src/pages/about/company.astro" ins="@components" ins="@assets"
---
import Button from '@components/controls/Button.astro';
import logoUrl from '@assets/logo.png?url';
---
```

## `import.meta.glob()`

[Vite 的 `import.meta.glob()`](https://cn.vite.dev/guide/features.html#glob-import) 是一种使用 glob 模式一次导入多个文件来查找匹配文件路径的方法。

`import.meta.glob()` 采用与你要导入的文件匹配的 [glob 模式](#glob-模式)，并返回每个匹配文件的导出的数组。要预先加载所有匹配的模块，请传递 `eager: true` 作为第二个参数。

```astro title="src/components/my-component.astro" {3,4}
---
// 导入`./src/pages/post/` 中所有以 `.md` 结尾的文件
const matches = import.meta.glob('../pages/post/*.md', { eager: true }); 
const posts = Object.values(matches);
---
<!-- 把前 5 篇博客文章渲染成 <article> -->
<div>
{posts.slice(0, 4).map((post) => (
  <article>
    <h2>{post.frontmatter.title}</h2>
    <p>{post.frontmatter.description}</p>
    <a href={post.url}>Read more</a>
  </article>
))}
</div>
```

使用 `import.meta.glob` 导入的 Astro 组件的类型为 [`AstroInstance`](#astro-文件)。你可以使用其 `default` 属性渲染每个组件实例：

```astro title="src/pages/component-library.astro" {8}
---
// 导入`./src/components/` 中所有以 `.astro` 结尾的文件
const components = Object.values(import.meta.glob('../components/*.astro', { eager: true }));
---
<!-- 展示所有组件-->
{components.map((component) => (
  <div>
    <component.default size={24} />
  </div>
))}
```
### 支持的值

Vite 的 `import.meta.glob()` 函数仅支持静态字符串字面量。它不支持动态变量和字符串插值。

一种常见的解决方法是导入一个包含所有你需要的文件的更大的文件集，然后对它们进行过滤：

```astro {6-7}
---
// src/components/featured.astro
const { postSlug } = Astro.props;
const pathToMyFeaturedPost = `src/pages/blog/${postSlug}.md`;

const posts = Object.values(import.meta.glob("../pages/blog/*.md", { eager: true }));
const myFeaturedPost = posts.find(post => post.file.includes(pathToMyFeaturedPost));
---

<p>
  Take a look at my favorite post, <a href={myFeaturedPost.url}>{myFeaturedPost.frontmatter.title}</a>!
</p>
```

### 导入类型工具函数

#### Markdown 文件

使用 `import.meta.glob()` 加载的 Markdown 文件返回以下 `MarkdownInstance` 接口：

```ts
export interface MarkdownInstance<T extends Record<string, any>> {
  /* 该文件的 YAML/TOML frontmatter 中指定的任何数据 */
	frontmatter: T;
  /* 该文件的绝对文件路径 */
	file: string;
  /* 该文件的渲染路径 */
	url: string | undefined;
  /* 渲染此文件内容的 Astro 组件 */
	Content: AstroComponentFactory;
  /** （仅限 Markdown）原始 Markdown 文件内容，不包括布局 HTML 和 YAML/TOML frontmatter */
	rawContent(): string;
  /** （仅限 Markdown）将 Markdown 文件编译为 HTML，不包括布局 HTML */
	compiledContent(): string;
  /* 返回此文件中的 h1...h6 元素数组的函数 */
	getHeadings(): Promise<{ depth: number; slug: string; text: string }[]>;
	default: AstroComponentFactory;
}
```

你可以选择使用 TypeScript 泛型为 `frontmatter` 变量提供类型。

```astro
---
import type { MarkdownInstance } from 'astro';
interface Frontmatter {
    title: string;
    description?: string;
}

const posts = Object.values(import.meta.glob<MarkdownInstance<Frontmatter>>('./posts/**/*.md', { eager: true }));
---

<ul>
  {posts.map(post => <li>{post.frontmatter.title}</li>)}
</ul>
```

#### Astro 文件

Astro 文件具有以下接口：

```ts
export interface AstroInstance {
  /* 该文件的文件路径 */
  file: string;
  /* 如果文件在 pages 目录中，则为此文件的 URL */
	url: string | undefined;
	default: AstroComponentFactory;
}
```

#### 其他文件

其他文件可能有各种不同的接口，但是如果你确切地知道一个未识别的文件类型包含什么，`import.meta.glob()` 接受一个 TypeScript 泛型。

```ts
---
interface CustomDataFile {
  default: Record<string, any>;
}
const data = import.meta.glob<CustomDataFile>('../data/**/*.js');
---
```

### Glob 模式

glob 模式是一个支持特殊通配符的文件路径。用于一次引用项目中的多个文件。

例如，glob 模式 `./pages/**/*.{md,mdx}` 从 pages 子目录开始，查找其所有子目录（`/**`），并匹配以 `.md` 或 `.mdx` 结尾的任何文件名（`.{md,mdx}`）。

#### Astro 中的 Glob 模式

要与 `import.meta.glob()` 一起使用，glob 模式必须是字符串字面量，并且不能包含任何变量。

此外，glob 模式必须以以下之一开头：
- `./`（从当前目录开始）
- `../`（从父目录开始）
- `/`（从项目根目录开始）

[阅读更多关于 glob 模式语法](https://github.com/micromatch/picomatch#globbing-features)


### `import.meta.glob()` vs `getCollection()`

[内容集合](/zh-cn/guides/content-collections/) 提供用于加载多个文件的 [`getCollection()` API](/zh-cn/reference/modules/astro-content/#getcollection) 代替 `import.meta.glob()`。如果你的内容文件 (例如 Markdown, MDX, Markdoc) 位于`src/content/` 目录内的集合中，使用 `getCollection()` [查询集合](/zh-cn/guides/content-collections/#查询集合)并返回内容条目。

## WASM

```js
// 加载并初始化所请求的 WASM 文件
const wasm = await WebAssembly.instantiateStreaming(fetch('/example.wasm'));
```

Astro 支持使用浏览器的 [`WebAssembly`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly) API 直接在应用程序中 WASM 文件。

## Node 内置模块

Astro 支持通过 Node.js 较新的 `node:` 前缀来调用其内置模块，但仍存在部分限制。比如可能在开发和生产环境中可能存在差异，且部分功能可能与按需渲染不兼容。部分 [适配器](/zh-cn/guides/on-demand-rendering/) 可能也与内置模块不兼容，或需要额外配置才能支持（例如 [Cloudflare Workers](/zh-cn/guides/integrations-guide/cloudflare/) 或 [Deno](https://github.com/denoland/deno-astro-adapter)）。

下面的示例展示了从 Node 中导入 `util` 模块，用以解析媒体类型（MIME）：

```astro title="src/components/MyComponent.astro"
---
// 示例：从 Node.js 中导入内置模块 "util"
import util from 'node:util';
export interface Props {
  mimeType: string,
}
const mime = new util.MIMEType(Astro.props.mimeType)
---
<span>Type: {mime.type}</span>
<span>SubType: {mime.subtype}</span>
```

## 扩展文件类型支持

使用 **Vite** 和兼容的 **Rollup** 插件，你可以导入 Astro 原生不支持的文件类型。在 Vite 文档的 [查找插件](https://cn.vite.dev/guide/using-plugins.html#finding-plugins) 部分了解你需要的插件。

:::note[插件配置]
请参阅插件的文档以了解配置选项以及如何正确安装它。
:::

<RecipeLinks slugs={["zh-cn/recipes/add-yaml-support"]} />
